package net.thxjj.netty;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import net.model.device.BaseBean;
import net.model.deviceresp.DevRespBean;
import net.model.device.LoginBean;
import net.thxjj.error.ActionType;
import net.thxjj.error.ErrCode;
import net.thxjj.extservice.MobileWebSocketClient;
import net.thxjj.service.IDeviceService;
import net.thxjj.service.IProductService;
import net.util.ParameterMap;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;


@Component
public class SpliterHandler extends HeartBeatBaseChannelInBoundHandler {
    private Logger log = Logger.getLogger(String.valueOf(this.getClass()));

    private static Map<String, SimpleChannelInboundHandler> handlerMap = null;

     private IDeviceService deviceService;
     private IProductService productService;
     private MobileWebSocketClient mobileWebSocketClient;

    //解码映射表
    Map<String, Class> codecMap = null;
    private static volatile SpliterHandler instance = null;

    public static SpliterHandler getInstance() {
        if (instance == null) {
            synchronized (SpliterHandler.class) {
                instance = new SpliterHandler();
                return instance;
            }
        }
        return instance;
    }

    public  SpliterHandler(IDeviceService deviceService,IProductService productService,MobileWebSocketClient mobileWebSocketClient) {
        handlerMap = new HashMap<>();
        this.deviceService = deviceService;
        this.productService = productService;
        this.mobileWebSocketClient = mobileWebSocketClient;
        DevLoginHandler devLoginHandler = new  DevLoginHandler();
        devLoginHandler.setDeviceService(deviceService);
        devLoginHandler.setProductService(productService);

        DeviceSendHandler deviceSendHandler = new DeviceSendHandler();
        deviceSendHandler.setProductService(this.productService);
        deviceSendHandler.setDeviceService(this.deviceService);
        deviceSendHandler.setMobileWebSocketClient(this.mobileWebSocketClient);
        handlerMap.put(ActionType.DEVICE_LOGIN.getName(), devLoginHandler);
        handlerMap.put(ActionType.DEVICE_SEND.getName(), deviceSendHandler);

        DeviceReportInfoHandler deviceReportInfoHandler = new DeviceReportInfoHandler();
        deviceReportInfoHandler.setDeviceService(this.deviceService);
        handlerMap.put(ActionType.DEVICE_REPORTINFO.getName(),deviceReportInfoHandler);
        handlerMap.put(ActionType.HEARTBEAT.getName(),new DeviceHeartHandler());

        codecMap = new HashMap<String, Class>();

        codecMap.put(ActionType.DEVICE_LOGIN.getName(), DevLoginHandler.class);
        codecMap.put(ActionType.DEVICE_SEND.getName(), DeviceSendHandler.class);
        codecMap.put(ActionType.DEVICE_REPORTINFO.getName(),DeviceReportInfoHandler.class);
        codecMap.put(ActionType.HEARTBEAT.getName(),DeviceHeartHandler.class);
    }

    public  SpliterHandler() {
        handlerMap = new HashMap<>();
        handlerMap.put(ActionType.DEVICE_LOGIN.getName(), new DevLoginHandler());
        handlerMap.put(ActionType.DEVICE_SEND.getName(), new DeviceSendHandler());
        handlerMap.put(ActionType.HEARTBEAT.getName(),new DeviceHeartHandler());

        codecMap = new HashMap<String, Class>();

        codecMap.put(ActionType.DEVICE_LOGIN.getName(), DevLoginHandler.class);
        codecMap.put(ActionType.DEVICE_SEND.getName(), DeviceSendHandler.class);
        codecMap.put(ActionType.HEARTBEAT.getName(),DeviceHeartHandler.class);
    }



    @Override
    protected void channelRead0(ChannelHandlerContext ctx, BaseBean reOb) throws Exception {

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        insertLoginOutEvent(ctx);
    }

    /**
     * channelRead
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        super.channelRead(ctx,msg);
        try {
            BaseBean baseBean =  JSONObject.parseObject((String)msg, BaseBean.class);
            if(handlerMap.containsKey(baseBean.getAction())){
                handlerMap.get(baseBean.getAction()).channelRead(ctx, (String)msg);
            }else{
                DevRespBean devRespBean =  new DevRespBean(baseBean.getMsgId(),ActionType.ERROR_RESP.getName(), ErrCode.ACTION_ERROR.getCode(),ErrCode.ACTION_ERROR.getDescription(),null);
                ctx.writeAndFlush(devRespBean.toString());
            }
        }catch (JSONException e){
            DevRespBean devRespBean =  new DevRespBean(0, ActionType.ERROR_RESP.getName(), ErrCode.JSON_FORMAT_ERROR.getCode(),ErrCode.JSON_FORMAT_ERROR.getDescription(),null);
            ctx.writeAndFlush(devRespBean.toString());
            if(!DeviceSocketMap.hasDevice(ctx.channel())){
                ctx.close();
            }

        }


    }

    /**
     * insertLoginInEvent
     * @param ctx,devTid,token
     * 添加设备下线日志，快照snap更新
     */
    private void insertLoginOutEvent(ChannelHandlerContext ctx){

        if(DeviceSocketMap.hasDevice(ctx.channel())){
            AttributeKey<String> key = AttributeKey.valueOf("device");
            String devTid = ctx.channel().attr(key).get();
            String dfaCurrent = ctx.channel().id().asLongText();
            Channel channel =DeviceSocketMap.getChannelByDevTid(devTid);
            String dfa =  channel.id().asLongText();
            if(dfa.equals(dfaCurrent)){
                ParameterMap parameterMap = new ParameterMap();
                parameterMap.put("device_id",devTid);
                this.deviceService.updateDeviceOffline(parameterMap);
                DeviceSocketMap.removeSocketDevice(ctx.channel());
            }
        }


    }


}
